{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Early Stopping Example\n",
    "In this notebook, we will train an Multi-Layer Perceptron (MLP) to classify images from the [MNIST database](http://yann.lecun.com/exdb/mnist/) hand-written digit database, and use early stopping to stop the training when the model starts to overfit to the training data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import libraries\n",
    "import torch\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load and Batch the Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torchvision import datasets\n",
    "import torchvision.transforms as transforms\n",
    "from torch.utils.data.sampler import SubsetRandomSampler\n",
    "\n",
    "def create_datasets(batch_size):\n",
    "\n",
    "    # percentage of training set to use as validation\n",
    "    valid_size = 0.2\n",
    "\n",
    "    # convert data to torch.FloatTensor\n",
    "    transform = transforms.ToTensor()\n",
    "\n",
    "    # choose the training and test datasets\n",
    "    train_data = datasets.MNIST(root='data', \n",
    "                                train=True,\n",
    "                                download=True, \n",
    "                                transform=transform)\n",
    "\n",
    "    test_data = datasets.MNIST(root='data',\n",
    "                               train=False,\n",
    "                               download=True,\n",
    "                               transform=transform)\n",
    "\n",
    "    # obtain training indices that will be used for validation\n",
    "    num_train = len(train_data)\n",
    "    indices = list(range(num_train))\n",
    "    np.random.shuffle(indices)\n",
    "    split = int(np.floor(valid_size * num_train))\n",
    "    train_idx, valid_idx = indices[split:], indices[:split]\n",
    "    \n",
    "    # define samplers for obtaining training and validation batches\n",
    "    train_sampler = SubsetRandomSampler(train_idx)\n",
    "    valid_sampler = SubsetRandomSampler(valid_idx)\n",
    "    \n",
    "    # load training data in batches\n",
    "    train_loader = torch.utils.data.DataLoader(train_data,\n",
    "                                               batch_size=batch_size,\n",
    "                                               sampler=train_sampler,\n",
    "                                               num_workers=0)\n",
    "    \n",
    "    # load validation data in batches\n",
    "    valid_loader = torch.utils.data.DataLoader(train_data,\n",
    "                                               batch_size=batch_size,\n",
    "                                               sampler=valid_sampler,\n",
    "                                               num_workers=0)\n",
    "    \n",
    "    # load test data in batches\n",
    "    test_loader = torch.utils.data.DataLoader(test_data,\n",
    "                                              batch_size=batch_size,\n",
    "                                              num_workers=0)\n",
    "    \n",
    "    return train_loader, test_loader, valid_loader"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the Network\n",
    "Defining a simple MLP model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Net(\n",
      "  (fc1): Linear(in_features=784, out_features=128, bias=True)\n",
      "  (fc2): Linear(in_features=128, out_features=128, bias=True)\n",
      "  (fc3): Linear(in_features=128, out_features=10, bias=True)\n",
      "  (dropout): Dropout(p=0.5)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__()\n",
    "        self.fc1 = nn.Linear(28 * 28, 128)\n",
    "        self.fc2 = nn.Linear(128, 128)\n",
    "        self.fc3 = nn.Linear(128, 10)\n",
    "        self.dropout = nn.Dropout(0.5)\n",
    "    def forward(self, x):\n",
    "        # flatten image input\n",
    "        x = x.view(-1, 28 * 28)\n",
    "        # add hidden layer, with relu activation function\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.dropout(x)\n",
    "        # add hidden layer, with relu activation function\n",
    "        x = F.relu(self.fc2(x))\n",
    "        x = self.dropout(x)\n",
    "        # add output layer\n",
    "        x = self.fc3(x)\n",
    "        return x\n",
    "\n",
    "# initialize the NN\n",
    "model = Net()\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Specify Loss Function and Optimizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# specify loss function\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "\n",
    "# specify optimizer\n",
    "optimizer = torch.optim.Adam(model.parameters())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import the Early Stopping Class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import EarlyStopping\n",
    "from pytorchtools import EarlyStopping"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Train the Model using Early Stopping"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_model(model, batch_size, patience, n_epochs):\n",
    "    \n",
    "    # to track the training loss as the model trains\n",
    "    train_losses = []\n",
    "    # to track the validation loss as the model trains\n",
    "    valid_losses = []\n",
    "    # to track the average training loss per epoch as the model trains\n",
    "    avg_train_losses = []\n",
    "    # to track the average validation loss per epoch as the model trains\n",
    "    avg_valid_losses = [] \n",
    "    \n",
    "    # initialize the early_stopping object\n",
    "    early_stopping = EarlyStopping(patience=patience, verbose=True)\n",
    "    \n",
    "    for epoch in range(1, n_epochs + 1):\n",
    "\n",
    "        ###################\n",
    "        # train the model #\n",
    "        ###################\n",
    "        model.train() # prep model for training\n",
    "        for batch, (data, target) in enumerate(train_loader, 1):\n",
    "            # clear the gradients of all optimized variables\n",
    "            optimizer.zero_grad()\n",
    "            # forward pass: compute predicted outputs by passing inputs to the model\n",
    "            output = model(data)\n",
    "            # calculate the loss\n",
    "            loss = criterion(output, target)\n",
    "            # backward pass: compute gradient of the loss with respect to model parameters\n",
    "            loss.backward()\n",
    "            # perform a single optimization step (parameter update)\n",
    "            optimizer.step()\n",
    "            # record training loss\n",
    "            train_losses.append(loss.item())\n",
    "\n",
    "        ######################    \n",
    "        # validate the model #\n",
    "        ######################\n",
    "        model.eval() # prep model for evaluation\n",
    "        for data, target in valid_loader:\n",
    "            # forward pass: compute predicted outputs by passing inputs to the model\n",
    "            output = model(data)\n",
    "            # calculate the loss\n",
    "            loss = criterion(output, target)\n",
    "            # record validation loss\n",
    "            valid_losses.append(loss.item())\n",
    "\n",
    "        # print training/validation statistics \n",
    "        # calculate average loss over an epoch\n",
    "        train_loss = np.average(train_losses)\n",
    "        valid_loss = np.average(valid_losses)\n",
    "        avg_train_losses.append(train_loss)\n",
    "        avg_valid_losses.append(valid_loss)\n",
    "        \n",
    "        epoch_len = len(str(n_epochs))\n",
    "        \n",
    "        print_msg = (f'[{epoch:>{epoch_len}}/{n_epochs:>{epoch_len}}] ' +\n",
    "                     f'train_loss: {train_loss:.5f} ' +\n",
    "                     f'valid_loss: {valid_loss:.5f}')\n",
    "        \n",
    "        print(print_msg)\n",
    "        \n",
    "        # clear lists to track next epoch\n",
    "        train_losses = []\n",
    "        valid_losses = []\n",
    "        \n",
    "        # early_stopping needs the validation loss to check if it has decresed, \n",
    "        # and if it has, it will make a checkpoint of the current model\n",
    "        early_stopping(valid_loss, model)\n",
    "        \n",
    "        if early_stopping.early_stop:\n",
    "            print(\"Early stopping\")\n",
    "            break\n",
    "        \n",
    "    # load the last checkpoint with the best model\n",
    "    model.load_state_dict(torch.load('checkpoint.pt'))\n",
    "\n",
    "    return  model, avg_train_losses, avg_valid_losses"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  1/100] train_loss: 0.84499 valid_loss: 0.29977\n",
      "[  2/100] train_loss: 0.36182 valid_loss: 0.22742\n",
      "Validation loss decreased (inf --> 0.227419).  Saving model ...\n",
      "[  3/100] train_loss: 0.29205 valid_loss: 0.19163\n",
      "Validation loss decreased (0.227419 --> 0.191628).  Saving model ...\n",
      "[  4/100] train_loss: 0.25390 valid_loss: 0.16771\n",
      "Validation loss decreased (0.191628 --> 0.167714).  Saving model ...\n",
      "[  5/100] train_loss: 0.22671 valid_loss: 0.15422\n",
      "Validation loss decreased (0.167714 --> 0.154222).  Saving model ...\n",
      "[  6/100] train_loss: 0.20862 valid_loss: 0.14546\n",
      "Validation loss decreased (0.154222 --> 0.145459).  Saving model ...\n",
      "[  7/100] train_loss: 0.19482 valid_loss: 0.13821\n",
      "Validation loss decreased (0.145459 --> 0.138206).  Saving model ...\n",
      "[  8/100] train_loss: 0.18431 valid_loss: 0.13398\n",
      "Validation loss decreased (0.138206 --> 0.133979).  Saving model ...\n",
      "[  9/100] train_loss: 0.17554 valid_loss: 0.12953\n",
      "Validation loss decreased (0.133979 --> 0.129535).  Saving model ...\n",
      "[ 10/100] train_loss: 0.16785 valid_loss: 0.12202\n",
      "Validation loss decreased (0.129535 --> 0.122023).  Saving model ...\n",
      "[ 11/100] train_loss: 0.16202 valid_loss: 0.12249\n",
      "EarlyStopping counter: 1 out of 20\n",
      "[ 12/100] train_loss: 0.15300 valid_loss: 0.11852\n",
      "Validation loss decreased (0.122023 --> 0.118516).  Saving model ...\n",
      "[ 13/100] train_loss: 0.14965 valid_loss: 0.11560\n",
      "Validation loss decreased (0.118516 --> 0.115598).  Saving model ...\n",
      "[ 14/100] train_loss: 0.14680 valid_loss: 0.11387\n",
      "Validation loss decreased (0.115598 --> 0.113867).  Saving model ...\n",
      "[ 15/100] train_loss: 0.13988 valid_loss: 0.11728\n",
      "EarlyStopping counter: 1 out of 20\n",
      "[ 16/100] train_loss: 0.13641 valid_loss: 0.11269\n",
      "Validation loss decreased (0.113867 --> 0.112686).  Saving model ...\n",
      "[ 17/100] train_loss: 0.12957 valid_loss: 0.11237\n",
      "Validation loss decreased (0.112686 --> 0.112374).  Saving model ...\n",
      "[ 18/100] train_loss: 0.12862 valid_loss: 0.11198\n",
      "Validation loss decreased (0.112374 --> 0.111975).  Saving model ...\n",
      "[ 19/100] train_loss: 0.12581 valid_loss: 0.10924\n",
      "Validation loss decreased (0.111975 --> 0.109242).  Saving model ...\n",
      "[ 20/100] train_loss: 0.12171 valid_loss: 0.10836\n",
      "Validation loss decreased (0.109242 --> 0.108363).  Saving model ...\n",
      "[ 21/100] train_loss: 0.12191 valid_loss: 0.10922\n",
      "EarlyStopping counter: 1 out of 20\n",
      "[ 22/100] train_loss: 0.11935 valid_loss: 0.10976\n",
      "EarlyStopping counter: 2 out of 20\n",
      "[ 23/100] train_loss: 0.11901 valid_loss: 0.11053\n",
      "EarlyStopping counter: 3 out of 20\n",
      "[ 24/100] train_loss: 0.11420 valid_loss: 0.10901\n",
      "EarlyStopping counter: 4 out of 20\n",
      "[ 25/100] train_loss: 0.11089 valid_loss: 0.10837\n",
      "EarlyStopping counter: 5 out of 20\n",
      "[ 26/100] train_loss: 0.11008 valid_loss: 0.10944\n",
      "EarlyStopping counter: 6 out of 20\n",
      "[ 27/100] train_loss: 0.10801 valid_loss: 0.10665\n",
      "Validation loss decreased (0.108363 --> 0.106647).  Saving model ...\n",
      "[ 28/100] train_loss: 0.10433 valid_loss: 0.10248\n",
      "Validation loss decreased (0.106647 --> 0.102475).  Saving model ...\n",
      "[ 29/100] train_loss: 0.10323 valid_loss: 0.10621\n",
      "EarlyStopping counter: 1 out of 20\n",
      "[ 30/100] train_loss: 0.10484 valid_loss: 0.10775\n",
      "EarlyStopping counter: 2 out of 20\n",
      "[ 31/100] train_loss: 0.09985 valid_loss: 0.10616\n",
      "EarlyStopping counter: 3 out of 20\n",
      "[ 32/100] train_loss: 0.09898 valid_loss: 0.10479\n",
      "EarlyStopping counter: 4 out of 20\n",
      "[ 33/100] train_loss: 0.10062 valid_loss: 0.10576\n",
      "EarlyStopping counter: 5 out of 20\n",
      "[ 34/100] train_loss: 0.09704 valid_loss: 0.10770\n",
      "EarlyStopping counter: 6 out of 20\n",
      "[ 35/100] train_loss: 0.09850 valid_loss: 0.10542\n",
      "EarlyStopping counter: 7 out of 20\n",
      "[ 36/100] train_loss: 0.09561 valid_loss: 0.10619\n",
      "EarlyStopping counter: 8 out of 20\n",
      "[ 37/100] train_loss: 0.09381 valid_loss: 0.10745\n",
      "EarlyStopping counter: 9 out of 20\n",
      "[ 38/100] train_loss: 0.09363 valid_loss: 0.10487\n",
      "EarlyStopping counter: 10 out of 20\n",
      "[ 39/100] train_loss: 0.09263 valid_loss: 0.10763\n",
      "EarlyStopping counter: 11 out of 20\n",
      "[ 40/100] train_loss: 0.09234 valid_loss: 0.10778\n",
      "EarlyStopping counter: 12 out of 20\n",
      "[ 41/100] train_loss: 0.08485 valid_loss: 0.10319\n",
      "EarlyStopping counter: 13 out of 20\n",
      "[ 42/100] train_loss: 0.09105 valid_loss: 0.10305\n",
      "EarlyStopping counter: 14 out of 20\n",
      "[ 43/100] train_loss: 0.08963 valid_loss: 0.10952\n",
      "EarlyStopping counter: 15 out of 20\n",
      "[ 44/100] train_loss: 0.08887 valid_loss: 0.10615\n",
      "EarlyStopping counter: 16 out of 20\n",
      "[ 45/100] train_loss: 0.08704 valid_loss: 0.10870\n",
      "EarlyStopping counter: 17 out of 20\n",
      "[ 46/100] train_loss: 0.08477 valid_loss: 0.10877\n",
      "EarlyStopping counter: 18 out of 20\n",
      "[ 47/100] train_loss: 0.08397 valid_loss: 0.10682\n",
      "EarlyStopping counter: 19 out of 20\n",
      "[ 48/100] train_loss: 0.08630 valid_loss: 0.10565\n",
      "EarlyStopping counter: 20 out of 20\n",
      "Early stopping\n"
     ]
    }
   ],
   "source": [
    "batch_size = 256\n",
    "n_epochs = 100\n",
    "\n",
    "train_loader, test_loader, valid_loader = create_datasets(batch_size)\n",
    "\n",
    "# early stopping patience; how long to wait after last time validation loss improved.\n",
    "patience = 20\n",
    "\n",
    "model, train_loss, valid_loss = train_model(model, batch_size, patience, n_epochs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualizing the Loss and the Early Stopping Checkpoint\n",
    "From the plot we can see that the last Early Stopping Checkpoint was saved right before the model started to overfit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsgAAAI4CAYAAAB3OR9vAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3Xl4VOXd//HPPZNMFrIACYQgKIsQshBCWJRFCIKWnRYpiIJEqyjWWrW0RX/WWuvzaC0qbri1gnVDBBdk0aoQZHEDRbaA7BpBVoGwBEhyfn8cMk+MAySQmTPJvF/XdV9DkjPnfEmO7Yc733PfxrIsAQAAALC5nC4AAAAACCYEZAAAAKAcAjIAAABQDgEZAAAAKIeADAAAAJRDQAYAAADK8WtANsb0NcasN8ZsNMZM8PH1XGPMbmPMipPjen/WAwAAAJxJmL9ObIxxS3pK0mWSCiR9YYyZZVnW2gqHvm5Z1i3+qgMAAACoCn/OIHeWtNGyrM2WZR2XNE3SED9eDwAAADhnfptBlnSepO/KfVwg6SIfx11hjOkh6RtJt1uW9V3FA4wxYyWNlaTIyMgO559/frUXu/uIpeOlls6LoS27JiotLZXLxc8OP8e9UTNEf2f/T/+Rpk0Dcj3uC/jCfVH7ffPNN3ssy2pwpuP8GZCNj89V3Nf6XUmvWZZ1zBhzk6QXJV36szdZ1nOSnpOklJQUa/369dVdq+54fYU+37pPi//8s8ujBsjLy1NOTo7TZSAIcW/UEGU/o7y8gFyO+wK+cF/UfsaYbZU5zp//TCqQVH4qoImk7eUPsCxrr2VZx05++LykDn6s57Q8YS4dLy516vIAAAAIEv6cQf5CUitjTHNJ30u6UtJV5Q8wxiRblrXj5IeDJeX7sZ7T8oS5dLyEgAwAjpg0yekKAMDLbwHZsqxiY8wtkt6X5Jb0gmVZa4wx90laZlnWLEm3GmMGSyqWtE9Srr/qOROPmxlkAHBMVpbTFQCAlz9nkGVZ1lxJcyt87p5yf75T0p3+rKGyaLEAAAd9+KH92qePs3WgSk6cOKGCggIVFRU5XUq1iI+PV36+Y7/MRjWKjIxUkyZNFB4eflbv92tArkk8YS4Vl1oqLbXkcvl6vhAA4Df332+/EpBrlIKCAsXGxqpZs2Yypub/f2dhYaFiY2OdLgPnyLIs7d27VwUFBWrevPlZnYO1TE4Kd9vfCvqQAQConKKiIiUkJNSKcIzawxijhISEc/rNBgH5pIgwAjIAAFVFOEYwOtf7koB8kqcsINOHDAAAENIIyCd53ARkAABqkr179yorK0tZWVlq1KiRzjvvPO/Hx48fr9Q5rr32Wp1pA7KnnnpKr7zySnWUrO7du2vFihXVci74Dw/pncQMMgA46Nlnna4ANVBCQoI3bN57772KiYnR+PHjf3KMZVmyLOuUW0hPmTLljNf57W9/e+7FokZhBvkkDz3IAOCclBR7ANVg48aNysjI0E033aTs7Gzt2LFDY8eOVceOHZWenq777rvPe2zZjG5xcbGaNm2qCRMmqF27durSpYt27dolSbr77rs16eRmNt27d9eECRPUuXNnpaSkaOnSpZKkw4cP64orrlC7du00cuRIdezYsdIzxUePHtWYMWPUtm1bZWdn6+OPP5YkrVq1Sp06dVJWVpYyMzO1efNmFRYWql+/fmrXrp0yMjI0Y8aM6vzW4SRmkE+ixQIAHPTuu/broEHO1oGz9rd312jt9oPVes60xnH666D0s3rv2rVrNWXKFD3zzDOSpAcffFD169dXcXGxevXqpWHDhiktLe0n7zlw4IB69uypBx98UHfccYdeeOEFTZgw4WfntixLn3/+uWbNmqX77rtP7733np544gk1atRIM2fO1Ndff63s7OxK1/r444/L4/Fo1apVWrNmjfr3768NGzZo8uTJGj9+vEaMGKFjx47Jsiy98847atasmebNm+etGdWPGeSTwplBBgDnPPywPYBq0rJlS3Xq1Mn78Wuvvabs7GxlZ2crPz9fa9eu/dl7oqKi1K9fP0lShw4dtHXrVp/nHjp06M+OWbx4sa688kpJUrt27ZSeXvlgv3jxYo0ePVqSlJ6ersaNG2vjxo3q2rWr7r//fj300EP67rvvFBkZqczMTL333nuaMGGClixZovj4+EpfB5XHDPJJEcwgAwBw1s52ptdf6tSp4/3zhg0b9Nhjj+nzzz9X3bp1NWrUKJ9r5Ho8Hu+f3W63iouLfZ47IiLiZ8dYlnXWtZ7qvaNHj1aXLl00Z84cXXbZZXrxxRfVo0cPLVu2THPnztUf//hHDRw4UHfddddZXxu+MYN8Eg/pAQBQOx08eFCxsbGKi4vTjh079P7771f7Nbp3767p06dLsnuHfc1Qn0qPHj28q2Tk5+drx44duvDCC7V582ZdeOGF+v3vf68BAwZo5cqV+v777xUTE6PRo0frjjvu0Jdfflntfxcwg+xFQAYAoHbKzs5WWlqaMjIy1KJFC3Xr1q3ar/G73/1O11xzjTIzM5Wdna2MjIxTtj/84he/UHh4uCTpkksu0QsvvKAbb7xRbdu2VXh4uP7zn//I4/Ho1Vdf1Wuvvabw8HA1btxY999/v5YuXaoJEybI5XLJ4/F4e6xRvcy5/ErACSkpKdaZ1is8G+t+OKi+kxZp8tXZ6t82udrPD//Ky8tTTk6O02UgCHFv1BBlP6O8vIBcjvuieuTn5ys1NdXpMqpNYWGhYmNjz+q9xcXFKi4uVmRkpDZs2KDLL79cGzZsUFgYc5FO8XV/GmOWW5bV8Uzv5ad2UtkqFid4SA8AAu+ll5yuADgnhw4dUu/evVVcXCzLsvTss88SjmswfnInhZ8MyMdosQCAwGva1OkKgHNSt25dLV++3OkyUE14SO+kCHqQAcA5r79uDwAIAswgn8RDegDgoKeftl9HjHC2DgAQM8hebDUNAAAAiYDsxVbTAAAAkAjIXmFul1yGgAwAQE2Rk5Pzs00/Jk2apJtvvvm074uJiZEkbd++XcOGDTvluZctW3ba80yaNElHjhzxfty/f3/t37+/MqWf1r333quJEyee83lw9gjI5XjCXCzzBgBADTFy5EhNmzbtJ5+bNm2aRo4cWan3N27cWDNmzDjr61cMyHPnzlXdunXP+nwIHgTkcsLdLpZ5AwAnzJhhD6AKhg0bptmzZ+vYsWOSpK1bt2r79u3q3r27d13i7OxstW3bVu+8887P3r9161ZlZGRIko4eParc3FxlZmZqxIgROnr0qPe4cePGqWPHjkpPT9df//pXSdLjjz+u7du3q1evXurVq5ckqVmzZtqzZ48k6ZFHHlFGRoYyMjI0adIk7/VSU1N1ww03KD09XZdffvlPrnMmvs55+PBhDRgwQO3atVNGRoZeP7kazIQJE5SWlqbMzEyNHz++St9XsIrFT0SEuXhIDwCckJjodAU4V/MmSD+sqt5zNmor9XvwlF9OSEhQ586d9d5772nIkCGaNm2aRowYIWOMIiMj9dZbbykuLk579uzRxRdfrMGDB8sY4/NcTz/9tKKjo7Vy5UqtXLlS2dnZ3q/9z//8j+rXr6+SkhL17t1bK1eu1K233qpHHnlECxYsUGKF+3f58uWaMmWKPvvsM1mWpYsuukg9e/ZUvXr1tGHDBr322mt6/vnnNXz4cM2cOVOjRo0647fiVOfcvHmzGjdurDlz5kiSDhw4oH379umtt97SunXrZIyplraPUMMMcjket4seZABwwtSp9gCqqHybRfn2CsuydNdddykzM1N9+vTR999/r507d57yPB9//LFGnFxmMDMzU5mZmd6vTZ8+XdnZ2Wrfvr3WrFmjtWvXnramxYsX61e/+pXq1KmjmJgYDR06VIsWLZIkNW/eXFlZWZKkDh06aOvWrZX6e57qnG3bttWHH36oP//5z1q0aJHi4+MVFxenyMhIXX/99XrzzTcVHR1dqWvg/zCDXI4njIAMAI4oC8e5uU5WgXNxmplef/rlL3+pO+64Q19++aWOHj3qnfl95ZVXtHv3bi1fvlzh4eFq1qyZioqKTnsuX7PLW7Zs0cSJE/XFF1+oXr16ys3NPeN5LMs65dciIiK8f3a73ZVusTjVOVu3bq3ly5dr7ty5uvPOO3X55Zfrnnvu0eeff66PPvpI06ZN05NPPqn58+dX6jqwMYNcDgEZAICaJSYmRjk5Obruuut+8nDegQMH1LBhQ4WHh2vBggXatm3bac/To0cPTZ8+XZK0evVqrVy5UpJ08OBB1alTR/Hx8dq5c6fmzZvnfU9sbKwKCwt9nuvtt9/WkSNHdPjwYb311lu65JJLzunveapzbt++XdHR0Ro1apTGjx+vL7/8UocOHdKBAwfUv39/TZo0SStWrDina4ciZpDLYRULAABqnpEjR2ro0KE/WdHi6quv1qBBg9SxY0dlZWWpTZs2pz3HuHHjNGrUKGVmZiorK0udO3eWJLVr107t27dXenq6WrRooW7dunnfM3bsWPXr10/JyclasGCB9/PZ2dnKzc31nuP6669X+/btK91OIUn333+/90E8SSooKPB5zvfff19//OMf5XK5FB4erqefflqFhYUaMmSIioqKZFmWHn300UpfFzZzul8DBKOUlBRr/fr1fjn30MlLVCciTC/95iK/nB/+k5eXp5ycHKfLQBDi3qghyn5GeXkBuRz3RfXIz89Xamqq02VUm8LCQsXGxjpdBqqJr/vTGLPcsqyOZ3ovLRblsMwbAAAAaLEoxxPmUmFRsdNlAEDomTvX6QoAwIuAXE5EmEt7mUEGgMBjGSoAQYQWi3I8bBQCAM6YPNkeABAECMjlsFEIADhk+nR7AEAQICCXwzJvAAAAICCXE84MMgAANYrb7VZWVpZ3PPhg1Xb0u/feezVx4sRKH//pp5/qoosuUlZWllJTU3XvvfdKspcOXLp0aZWuXVldu3attnN9/vnn6tGjh1JSUtSmTRtdf/31OnLkSJW/D6dSXeeZNWvWGX+WW7du1auvvnrO1/KFh/TKYSc9AABqlqioqLPeKa64uOorV40ZM0bTp09Xu3btVFJSorK9GfLy8hQTE1OtYbZMdQXvnTt36te//rWmTZumLl26yLIszZw50+dugE4bPHiwBg8efNpjygLyVVddVe3XZwa5HE+YS8dosQAAoMa777771KlTJ2VkZGjs2LEq2xgtJydHd911l3r27KnHHnvMe/ymTZt+sh30hg0b1KFDh5+dd9euXUpOTpZkz16npaVp69ateuaZZ/Too48qKytLixYt0rZt29S7d29lZmaqd+/e+vbbbyVJubm5uummm3TJJZeodevWmj17tiRp6tSpGjJkiPr27auUlBT97W9/814zJiZG0v9tcDNs2DC1adNGV199tffvNXfuXLVp00bdu3fXrbfeqoEDB/6s9qeeekpjxoxRly5dJEnGGA0bNkxJSUmSpLVr1yonJ0ctWrTQ448/7n3fyy+/rM6dOysrK0s33nijSkpKJEnvvfeesrOz1a5dO/Xu3ftn13v++efVr18/HT16VDk5ObrtttvUtWtXZWRk6PPPP5ck7du3T7/85S+VmZmpiy++2LvF99SpU3XLLbd4v2e33nqrunbtqhYtWmjGjBmSpAkTJmjRokXKysqq9t0CmUEuJ+Jki4VlWTLGOF0OAISOAO2gBz/ztTvh8OHSzTdLR45I/fv//Ou5ufbYs0caNuynX6vEfXH06FFlZWV5P77zzjs1YsQI3XLLLbrnnnskSaNHj9bs2bM1aNAgSdL+/fu1cOFCSfK2SLRs2VJxcXFasWKFsrKyNGXKFOXm5v7serfffrtSUlKUk5Ojvn37asyYMWrWrJluuukmxcTEaPz48ZKkQYMG6ZprrtGYMWP0wgsv6NZbb9Xbb78tyZ75XLhwoTZt2qRevXpp48aNkuz2h9WrVys6OlqdOnXSgAED1LHjTzd9++qrr7RmzRo1btxY3bp105IlS9SxY0fdeOON+vjjj9W8eXONHDnS5/dq9erVGjNmzCm/l+vWrdOCBQtUWFiolJQUjRs3Ths3btTrr7+uJUuWKDw8XDfffLNeeeUV9evXTzfccIP3mvv27fvJuZ588kn997//1dtvv62IiAhJ0uHDh7V06VJ9/PHHuu6667R69Wr99a9/Vfv27fX2229r/vz5uuaaa3z+RmDHjh1avHix1q1bp8GDB2vYsGF68MEHNXHiRO8/MqoTM8jleMLsb8eJkpq1/TYAAKGqrMWibIwYMUKStGDBAl100UVq27at5s+frzVr1njfU3ZMRddcc42mTJmikpISvf766z5/dX/PPfdo2bJluvzyy/Xqq6+qb9++Ps/1ySefeN8/evRoLV682Pu14cOHy+VyqVWrVmrRooXWrVsnSbrsssuUkJCgqKgoDR069CfvKdO5c2c1adJELpdLWVlZ2rp1q9atW6cWLVqoefPmknTKgHwmAwYMUEREhBITE9WwYUPt3LlTH330kZYvX65OnTopKytLH330kTZv3qxPP/1UPXr08F6zfv363vO89NJLmjdvnmbOnOkNx+Xr6tGjhw4ePKj9+/dr8eLFGj16tCTp0ksv1d69e3XgwIGf1fbLX/5SLpdLaWlp2rlz51n9/aqCGeRy/i8gl3r/DAAIgLKHek7OvqGGOt2Mb3T06b+emFhtv0koKirSzTffrGXLlqlp06a69957VVRU5P16nTp1fL5vyJAheuihh3TppZeqQ4cOSkhI8Hlcy5YtNW7cON1www1q0KCB9u7de8aayv9muuJvqcs+PtXnyysfON1ut4qLi71tFmeSnp6u5cuXa8iQIT6/fqpzjxkzRg888MBPjp01a9Ypf9uekZGhFStWqKCgwBugff19jDE+az/T37uyf99zQQosx+O2vx08qAcAATZ7tj2AalAWhhMTE3Xo0CFvz+qZREZG6he/+IXGjRuna6+91ucxc+bM8Qa0DRs2yO12q27duoqNjf3Jw25du3bVtGnTJEmvvPKKunfv7v3aG2+8odLSUm3atEmbN29WSkqKJOmDDz7Qvn37dPToUb399tvq1q1bpepu06aNNm/erK1bt0qSXn/9dZ/H3XLLLXrxxRf12WefeT/38ssv64cffjjluXv37q0ZM2Zo165dkuye4W3btqlLly5auHChtmzZ4v18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Eiggi4iIiIgkUEAWEREREUmggCwiIiIikkA36YmIiPc+/WmvKxARiVNAFhER711zjdcViIjEaYiFiIh4r67ObSIiw4B6kEVExHvXXedazYMsIsOAepBFRERERBIoIIuIiIiIJFBAFhERERFJoIAsIiIiIpJAN+mJiIj3brrJ6wpEROIUkEVExHuXXup1BSIicRpiISIi3lu92m0iIsOAepBFRMR7n/ykazUPsogMA+pBFhERERFJoIAsIiIiIpJAAVlEREREJIECsoiIiIhIAt2kJyIi3vuP//C6AhGROAVkERHx3vz5XlcgIhKnIRYiIuK9ZcvcJiIyDKgHWUREvHfjja7VPMgiMgyoB1lEREREJIECsoiIiIhIAgVkEREREZEECsgiIiIiIgl0k56IiHjvu9/1ugIRkTgFZBER8d6sWV5XICISpyEWIiLivZdecpuIyDCgHmQREfHe177mWs2DLCLDgHqQRUREREQSKCCLiIiIiCRQQBYRERERSaCALCIiIiKSQDfpiYiI92691esKRETiFJBFRMR7U6Z4XYGISJyGWIiIiPf+/ne3iYgMA+pBFhER791yi2vnz/e2DhER1IMsIiIiIrIPBWQRERERkQQKyCIiIiIiCRSQRUREREQS6CY9ERHx3u23e12BiEicArKIiHivpsbrCkRE4jTEQkREvPfww24TERkG1IMsIiLe+9GPXHvppd7WISKCepBFRERERPahgCwiIiIikkABWUREREQkgQKyiIiIiEgC3aQnIiLe++Mfva5ARCROAVlERLxXUeF1BSIicRpiISIi3rv7breJiAwD6kEWERHv/eIXrr3mGm/rEBFBPcgiIiIiIvtQQBYRERERSaCALCIiIiKSQAFZRERERCSBbtITERHv3Xuv1xWIiMQpIIuIiPfy872uQEQkTkMsRETEe3fe6TYRkWFAAVlERLyngCwiw4gCsoiIiIhIAgVkEREREZEECsgiIiIiIgkUkEVEREREEmiaNxER8d5jj3ldgYhInAKyiIh4LzXV6wpEROI0xEJERLz385+7TURkGFBAFhER791zj9tERIYBBWQRERERkQRDGpCNMRcYY1YbY9YZY74ywPPJxpi7Y8+/YowZNZT1iIiIiIi8myELyMYYP3AbcCEwEfgnY8zE/U77ONBora0GfgJ8f6jqERERERE5GEPZgzwT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\n",
      "text/plain": [
       "<Figure size 720x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# visualize the loss as the network trained\n",
    "fig = plt.figure(figsize=(10,8))\n",
    "plt.plot(range(1,len(train_loss)+1),train_loss, label='Training Loss')\n",
    "plt.plot(range(1,len(valid_loss)+1),valid_loss,label='Validation Loss')\n",
    "\n",
    "# find position of lowest validation loss\n",
    "minposs = valid_loss.index(min(valid_loss))+1 \n",
    "plt.axvline(minposs, linestyle='--', color='r',label='Early Stopping Checkpoint')\n",
    "\n",
    "plt.xlabel('epochs')\n",
    "plt.ylabel('loss')\n",
    "plt.ylim(0, 0.5) # consistent scale\n",
    "plt.xlim(0, len(train_loss)+1) # consistent scale\n",
    "plt.grid(True)\n",
    "plt.legend()\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "fig.savefig('loss_plot.png', bbox_inches='tight')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test the Trained Network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Loss: 0.085796\n",
      "\n",
      "Test Accuracy of     0: 98% (968/979)\n",
      "Test Accuracy of     1: 98% (1121/1133)\n",
      "Test Accuracy of     2: 97% (1008/1030)\n",
      "Test Accuracy of     3: 97% (986/1008)\n",
      "Test Accuracy of     4: 97% (955/980)\n",
      "Test Accuracy of     5: 97% (867/890)\n",
      "Test Accuracy of     6: 97% (932/956)\n",
      "Test Accuracy of     7: 97% (997/1027)\n",
      "Test Accuracy of     8: 96% (939/973)\n",
      "Test Accuracy of     9: 95% (967/1008)\n",
      "\n",
      "Test Accuracy (Overall): 97% (9740/9984)\n"
     ]
    }
   ],
   "source": [
    "# initialize lists to monitor test loss and accuracy\n",
    "test_loss = 0.0\n",
    "class_correct = list(0. for i in range(10))\n",
    "class_total = list(0. for i in range(10))\n",
    "\n",
    "model.eval() # prep model for evaluation\n",
    "\n",
    "for data, target in test_loader:\n",
    "    if len(target.data) != batch_size:\n",
    "        break\n",
    "    # forward pass: compute predicted outputs by passing inputs to the model\n",
    "    output = model(data)\n",
    "    # calculate the loss\n",
    "    loss = criterion(output, target)\n",
    "    # update test loss \n",
    "    test_loss += loss.item()*data.size(0)\n",
    "    # convert output probabilities to predicted class\n",
    "    _, pred = torch.max(output, 1)\n",
    "    # compare predictions to true label\n",
    "    correct = np.squeeze(pred.eq(target.data.view_as(pred)))\n",
    "    # calculate test accuracy for each object class\n",
    "    for i in range(batch_size):\n",
    "        label = target.data[i]\n",
    "        class_correct[label] += correct[i].item()\n",
    "        class_total[label] += 1\n",
    "\n",
    "# calculate and print avg test loss\n",
    "test_loss = test_loss/len(test_loader.dataset)\n",
    "print('Test Loss: {:.6f}\\n'.format(test_loss))\n",
    "\n",
    "for i in range(10):\n",
    "    if class_total[i] > 0:\n",
    "        print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (\n",
    "            str(i), 100 * class_correct[i] / class_total[i],\n",
    "            np.sum(class_correct[i]), np.sum(class_total[i])))\n",
    "    else:\n",
    "        print('Test Accuracy of %5s: N/A (no training examples)' % (classes[i]))\n",
    "\n",
    "print('\\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (\n",
    "    100. * np.sum(class_correct) / np.sum(class_total),\n",
    "    np.sum(class_correct), np.sum(class_total)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize Sample Test Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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rl27FrQvKDz/+uWBBx6I3Pb+++838SOPPOLkli9fXrodQ85q167ttO3rYL/EwW+//WbiQpdbkNz+fP75507OPof6ZYm+//77/HYMGdWsWdPEfsm5PfbYw8SHHXaYk6NsBtazyxhK0iWXXGJiu0SZJFWrVs1pB0Gw0cdv2rTpRn8GUJa4UxcAAAAAAAAAYoRFXQAAAAAAAACIERZ1AQAAAAAAACBGyrymbpcuXZy2XTfll19+cXIrVqww8VNPPeXkfv31VxNTW6niadCggYn92jp2/TC/XuHs2bOz+vwrr7zSae+2226R27766qtZfSYqFruumCRdeumlJn7yyScL3R3k2T/+8Q+n3alTJxPvt99+OX/uIYccYuJKldzfy06cONHE7733Xs7HQGFVqfK/S7EOHTqUYU/+WsfyiiuuMPEWW2zh5Pxa4Ig/e36RpO233z5y22HDhpnYvj5H2dtqq61M/Oyzzzq5OnXqmNivmXzZZZflt2Mb0KdPHxPvtNNOTu6CCy4wMd/zylb37t2d9k033WTiHXbYIXI/u/auJM2bN690O4bY8s81PXr0yPsxp06damL/nTuInyZNmpjYPgdKf33fUtu2bU28du1aJzd48GATf/DBB06uPJ97uFMXAAAAAAAAAGKERV0AAAAAAAAAiJEyL79w++23O+0dd9wxq/3sx3Ak6Y8//jBxWdxCP2vWLBP7f6bPPvus0N2pcF5++WUT27ffS+7YmD9/fk6f37VrV6e9ySab5PQ5qLh23XVXp20/yuw/Hon4u/vuu522/3hPrk444YS0sSTNmDHDxCeffLKT8x+rR/nRrl07Ex944IFOzr+eyLfatWs7bbvU0Oabb+7kKL8Qf5tttpnT7t27d9b72mWDwjAstT5h47Vo0cLE9mOmvn79+hWgN9F23313p22XOhs5cqST4zqpbNmPx99zzz1Orm7duibONBfcd999TtsuQybl/h0N5Yf/2LtdRsF/lH306NEm/vPPP53cokWLTOxfa/iloN58800Tf/31107u448/NvEXX3zh5JYvXx55DJRPdilDf/6wvxP547Ak9t9/fxOvXr3ayX377bcmHjdunJOzx/rKlStzPn6uuFMXAAAAAAAAAGKERV0AAAAAAAAAiBEWdQEAAAAAAAAgRsq8pu55553ntPfaay8TT5kyxck1a9bMxHa9KMmtGXXAAQc4uZ9++snEO+ywQ9Z98+tozJkzx8QNGjSI3G/mzJlOm5q6hWXXldwYPXv2NHHTpk0zbmvX7LFjYL2rr77aadvjlDmiOLz22msmrlSpdH5nOm/ePKe9ZMkSEzdq1MjJ7bTTTib+5JNPnFzlypVLpT/YeHZNMEkaNmyYiadPn+7kbr755oL0ab3jjjuuoMdD2dpzzz2ddsuWLSO39a+JX3/99bz0CSVXv359p925c+fIbc855xwT299rCsWuo/vWW29FbufX1LXfj4HCu+qqq0xcp06dnD7Dr/V/5JFHOu2bbrrJxH793bKoUYns2DVu7fq2krT33nub+Pjjj4/8jI8++shp2+s8P/74o5Nr2LCh07bfa1Ra769A2bHXAi+55BInZ88hNWvWjPyMn3/+2Wm///77Tvu///2vif3v5/Y7SPbbbz8nZ899HTp0cHITJ0408eDBgyP7li/cqQsAAAAAAAAAMcKiLgAAAAAAAADESJmXX3j77bcztm2jR4+OzNWuXdvE++yzj5Ozb6Ped999s+7bihUrnPa0adNM7JeGsG/H9h+fRDwcc8wxTrtfv34m3nTTTZ3c77//7rSvvfZaEy9btiwPvUPc7Ljjjk67VatWTtueT5YuXVqILqGUtWnTxmnvsssuJvYfAcv2kTD/kR3/UbZFixaZuH379k6ud+/ekZ970UUXmXjQoEFZ9QX50adPH6dtP7roP45ql9vIF/v6xR/TPMpY3DI9pu/z5yKUH3fddZfTPvXUU01sfweSpOeff74gfYrSunVrE2+99dZO7rHHHjPx0KFDC9UlpOGXdzrrrLMit500aZKJf/vtNyd32GGHRe635ZZbOm27xMNTTz3l5H799dfozqKg/O/ETz/9tIntcguSW0IqU7kVn19yweaXuUS8Pfjgg07bLtOx1VZbRe7nrxl+9dVXJr7uuuucnL+mZzvooIOctv196ZFHHnFy9hqjP9cNHDjQxC+88IKTK0SpI+7UBQAAAAAAAIAYYVEXAAAAAAAAAGKERV0AAAAAAAAAiJEyr6lbWhYsWGDid999N3K7TDV7N8SuPWbX8JXcOh7PPvtszsdA2fFrnvo1g2z+3/HYsWPz0ifEl1+b0leI+joofXat5GeeecbJZar9ZJsxY4bTtmsvJZNJJ5epRrf/Oeeff76J69Wr5+Ruv/12E1etWtXJ3X///SZetWpV5PGQuy5dupi4Q4cOTu7777838WeffVawPq1n12L2a+iOGTPGxAsXLixUl1AghxxySMb8ypUrTZypZjfKVhiGTtv+d/zLL784OfvvNF+qVatmYr+24cUXX2xiv99nn312fjuGrPnvp6lRo4aJ33//fSdnX+/61xennHKKif2x0LhxY6e9zTbbmPill15yckcddZSJ58+fn7HvKH3Vq1c3sf0eGcl9J83cuXOd3J133mli3jlTcfnzwtVXX23ic88918kFQWBi/7uy/U6QO+64w8nl+n6aunXrOu3KlSubuG/fvk7Ofr+XX3e8rHGnLgAAAAAAAADECIu6AAAAAAAAABAjRVN+IR/q16/vtB944AETV6rkrof369fPxDwWEh8vvviiiQ8//PDI7Z544gmn3adPn7z1CcVhzz33zJi3H4dHfFSp8r/TZrblFiS3REvXrl2dnP+4Wrb88gu33HKLiQcMGODkNt98cxP7Y2/UqFEmnj59ek59QWYnnniiie2/C8m9tigEu4SIJHXv3t3Ea9ascXI33nijiSnNURwOOuigtHE69uOMX375Zd76hPw5+uijnfabb75pYr+kiv1oa0n45abatm1r4gMOOCByv+HDh+d0POTfZptt5rTtUhl333135H4rVqxw2o8++qiJ7fOgJO28886Rn+M/ql+IsiGI1qlTJxP36tXLyc2cOdPErVu3dnKLFi3Kb8cQC/Y5QZJ69uxpYrvcgiT9/PPPJrZLn0rSJ598ktPx7ZIKkrTDDjuY2F/jee2110zsl1u1+f1+8sknTVwW5cq4UxcAAAAAAAAAYoRFXQAAAAAAAACIERZ1AQAAAAAAACBGqKmbwSWXXOK069WrZ+IFCxY4uW+//bYgfcLGadCggdO268n59aPsOpd2XUFJWrJkSR56h7iza8edddZZTu6LL75w2v/5z38K0ieUjc8++8xpn3322SbOtYbuhti1ce06qZK077775uWYSG/LLbd02pnqSuZaxzJX559/vtO2a0NPmTLFyb377rsF6RMKpyRzQaHHJnJz7733Ou127dqZeNttt3VyhxxyiIn9moDHHntsTsf3P8euv+r74YcfTHzdddfldDzk3ymnnBKZ8+s02+8nyaRVq1ZZH/+jjz5y2nzvKluZ6q/b329mzZpViO4gZvyatv77G2yrV6828f77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yM+oVauW0862jIT9SIwkXXPNNSZetmxZVp+B3BxzzDGRuZdffrmAPUGh2I9yVaoU/XvRTI+nDhkyxGlvu+22kdv6x1i7du2GuphWx44dc9oP+ffll1+mjUvTDz/8kNV2e+yxh9P++uuv89Ed5NlBBx1k4kzz1IsvvliI7qDI+Oe3pUuXOu277rqrkN1BEXruueectl1+4eSTT3Zydik9SieWL2+//XZkzi495ZdfWL16tYkfffRRJ/fQQw857X/+858mzlRuCPG33377mdg/z1SvXj1yP7/E5oUXXmjiP//8s5R6V7a4UxcAAAAAAABEcNG5AAAgAElEQVQAYoRFXQAAAAAAAACIERZ1AQAAAAAAACBGirKmrl8nd/To0SbeaaednNz06dOd9vXXX5+/jqHcmTRpUql8zvPPP2/i2bNnO7mtt97axH4dqHz49ddfTXzTTTfl/XgVzcEHH2zibbbZpgx7grIwaNAgE99+++2R273yyitOO1Mt3JLUyc1228GDB2f9mSh+di1oO/ZRQ7c42O+S8M2dO9fE9957byG6gyJg1yC0r2sl6ffff3faEyZMKEifULz8ax37euu4445zcolEwsTPPPOMk5s2bVoeeofS8Oabb5rY/75apcr/lqjOO+88J9ekSROn3bZt26yON2vWrBL2EOWN/X6QGjVqRG7n13m3a3JL0gcffFC6HSsHuFMXAAAAAAAAAGKERV0AAAAAAAAAiJGiLL/QuHFjp92yZcvIba+44gqn7ZdjQPy89tprTtt/TCcfTjzxxJz2W716tYkzPVY9atQop/3ZZ59Fbvv+++/n1Bdk5/jjjzexX+rliy++MPF7771XsD6hcEaMGGHinj17Orl69erl/fhz5swx8ZQpU5zc+eefb2K/DAwqtjAM08YoTkcccURkbubMmSZetGhRIbqDImCXX/DnkFdffTVyP/8R2dq1a5vYHotAJl9++aWJb7jhBid3xx13mPjmm292cqeddpqJly9fnqfeIRf2Nexzzz3n5E466aTI/dq1axeZW7NmjdO256ZevXqVtIsoY/754+qrr85qv6eeesppjxkzprS6VG5xpy4AAAAAAAAAxAiLugAAAAAAAAAQIyzqAgAAAAAAAECMFE1N3UaNGpn4zTffjNzOr4H4yiuv5K1PKBsnnHCC07brr2yyySZZf87uu+9u4pNP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eHTnzp0j99tqq62c9tlnnx3dWcSSX2Ih220pvxBPgwcPdtr2XOCXBJs6daqJ77333sicf03sl1hAxWLPEyeccIKTs8832267rZObMGGC037++edNfOutt5ZiDwGUhWuvvdbEvXr1yukzKleu7LS7detmYruMpiSdddZZJqbUD/KpUiX3Hld7LH7zzTeF7k7OuFMXAAAAAAAAAGKERV0AAAAAAAAAiBEWdQEAAAAAAAAgRsp1Td3dd9/daXfp0iVy21mzZpn49NNPd3Lff/+9iRcuXOjklixZEvmZfo2NG264wcR9+vRxcjVr1jRxIpFwcueee66JFyxYEHk85EeNGjVMvGrVKidn19QFSmqfffZx2v379zdxhw4dnJw/n9i1UocPH+7kevfubeLZs2c7uXbt2pn47bffdnLLly/PptsogAsuuMBp33jjjTl9ztixY532IYccktV+/nmQmroVW9++fcu6C9hII0aMcNqdOnUysV0nV5L23XffgvQJ8WO/Z8IfU/vtt5+J/feK2N+zvv32WyfXsGFDp22f72bMmOHkhg0bVsIeY2McddRRTvvFF180sV/7PxP7+nLUqFGR2/l/33ZN7/3339/JzZ0712mPGzcu6/6gsH788cfInF3ffeDAgU5u8uTJJvbHW79+/Uzsv//mpZdeMrH9TiVJuv322522X1MeKInmzZs7bf+dJHHBnboAAAAAAAAAECMs6gIAAAAAAABAjJTr8gv2Y/OSVLduXRPbt/pL7q35Y8aMKZXj249HS+7ji5tuuqmTu+qqq0x8/PHHO7lHHnnExK+++mqp9A3Rtt12W6d9zjnnmHj8+PFObsKECQXpE+LLf1yoTZs2Jn700UedXIMGDUzsz1H+fGLnO3fu7OTsx9x22GEHJ9e2bVsTn3HGGU5u6NChf+k/CscuGXT99dfn9Bm9evVy2vaji5L7uFrPnj1zOgaA+LnoooucdsuWLU3cqFEjJ2c/Dj9z5sz8dgzlmv8oqf09xC8hZY8Vv4TQxx9/bOJFixY5Of86xX50+sQTT3Ryzz77bGTuiy++MPF3333n5PxrKmTHnxtKUnLBVq1aNROffPLJWe93+eWXRx7bvy62x5hfluybb74xsV8KwC8HgtJnl/vxPf/88ybu0aNH1p85ceJEE48cOdLJ1alTx8T+9XTjxo2dtl1ezC+ziPhp2rSpie+8804nd9lll5nYL/WSD1999VXej1FauFMXAAAAAAAAAGKERV0AAAAAAAAAiBEWdQEAAAAAAAAgRsp1Td3NNtssMvf444877YEDB+a7O47rrrvOadv1hXbaaScnd8IJJ5iYmrr516dPn7LuguOAAw4wsV93zGbXFpKkadOm5a1PyF6LFi2c9ujRoyO3nT17tokvvfRSJ7ds2bLI/fyaZ0uXLjXxfffd5+RWrlyZ9ngoPLuGriTdcsstJvbrGNr1AP06UMcee6yJp0yZ4uT8mnM33HCDif0aZKNGjYo8/qRJk0y81157CfGXTCZNnEgkMm5rvxPAjhEfc+bMcdpDhgwx8Y033ujk7H//1NSt2Pza63Yd3V9++cXJ7bLLLia2rzU25KeffnLadq3cP//808l16NDBxE8//XTkZ1avXt1p2+8aQPYefvhhp23XHG3SpImTyzRXVK1a1cTHHXdc1sdv1qyZievVq+fkKlVy7y078MAD08a+FStWOO077rjDxBs6FyI39r9b/7rUP/9ka9y4cSb2x5R9PX3wwQc7uW7dukV+5llnneW0V69enVPfUHbsdZNjjjnGydnrf6VVU9efB20///xzqRyjELhTFwAAAAAAAABihEVdAAAAAAAAAIiRcl1+oX///pG5jz/+uIA92bA33njDxBdeeKGTs28jR/4dffTRkTn/MaTSMmjQoMjj165d28TVqlWL/IzFixc77bvvvtvEmf4toPTZj9Xbj7T73n77bad97bXXmnjChAlZH2/bbbd12i+99JKJa9Wq5eTsx8z846Ow/NIc9r99/7FC+1HWBx54wMlNnjw562Paj05+8sknTu6xxx4z8ZVXXunk9txzTxPbj21L0vnnn5/18VF+8JhpxWbPMUEQODn7kWc/l4lf/iVT2SCUX127djXxFVdc4eTmz59vYnucSCUruZDJ9OnTTbzbbrs5uSeeeCJyP/vax3/EHrmxrxmk0vkeZH8/2ZA99tjDxH//+98zbms/Vt+yZcvI7exSEJLUo0cPEw8YMMDJLVq0KKt+IrO33nrLxO3bt3dydsm4XI0fP95pX3311Sb2S1fa36sld9y8/PLLTu65557b6L6hsPzxZctHOQT/O9DChQtNXJLv8mWNO3UBAAAAAAAAIEZY1AUAAAAAAACAGGFRFwAAAAAAAABipNzV1N15551N7NeZtOvifPXVVwXrUzbeeecdE/s1dZF/m2++uYmrVHGHtV1/xa45uSH25/i1M0eOHOm0t9lmGxP7tTTnzJljYrsmkf+5DRs2dHJ2jRe/BtmMGTMy9h0b5/rrrzfxVltt5eTs2k5+rbrvv/8+p+PZNcckqXnz5pHbjh49OqdjoPQdddRRTjsMQxOvXbvWyY0ZM8bEd911V17606tXr8i+2WOsVatWeTk+gPypV6+e0z733HNNbM89kvT444+b2K+pa2/r5/xrm6eeeioyh/Jrr732MrF/TWrXcF+yZEne+zJr1qyst/3jjz9M7I9pxNPXX3+dNk7Hfj/Jdttt5+Ts65tzzjnHydWsWdPE/vsEbrjhhuw7i0h2vfVMNU999nnKrn0rSQ8++GBWnzFs2DCnffHFF0du+7e//S3rvqF8qFGjhtM+9NBDTezXRPbfJVIaNtlkE6dtf39bvXp1qR8vX7hTFwAAAAAAAABihEVdAAAAAAAAAIiRcld+4dRTTzWxXYpBkl544QUTjx8/vmB9QvlnP96x9dZbO7khQ4Zk9Rl+uQ+7/EGfPn0y7vvLL7+Y+Mknn3RyDzzwgIkzPYY2atQop92hQwcTN2jQwMlRfqF0PfTQQ077xBNPNPHSpUudnP0IWK7lFiT3cY9rr73WydmPxI4dO9bJ+W0UVt26dU283377Zb2fPy/km3+82267raDHB7Dx7JIL/txvl2yaMGGCk7MflR03blzk55933nlOu2XLlk77hBNOMLH/OLw9/9nHk6Rly5ZFHhP517hx48hcoc8FRxxxhNOuVq1a5Lb+o7aoWFasWGHi6dOnOzl73PrlF+yyHSUps4fsffbZZ5E5u9xL1apVndz9999vYv8x9zZt2pRS7/7HXg+QpG+//dbE//nPf5ycXdYTZWe33XZz2nbplY8//tjJ+aXtclWrVi0TN2vWzMn54yQuuFMXAAAAAAAAAGKERV0AAAAAAAAAiBEWdQEAAAAAAAAgRspdTd2uXbua2K91cu+99xa6O4iJ5s2bR+a+++67rD7Dr5t7wQUXmNivJffOO+847csvv9zEkydPzup4vmz7idLXqlUrp23/fS9ZssTJffPNNzkdw68l1b9/fxO3bt068vj9+vXL6XjID7vm5I477hi53fvvv++0X3311Xx1qcRq167ttO2a3bNnzy50dwBE2GWXXdLGkjRixAgT23XgS8J/58BWW23ltO33XHTq1MnJffLJJyb2z4t2f6ZOnZpT35C9zTff3Gkff/zxkdva74DIl0033dTEN998c2TOv776+uuv89sxxNZxxx0XmatRo4aJu3Tp4uRuv/32vPWpInnxxRdN7Nc1tb8T+++1sesk+9+D8sGuNS9Jzz77rIn9Wu/2u3NeeuklJ0dd+MI5+OCDI3P5eo/MySefbGL7XSmS9N577+XlmPnGnboAAAAAAAAAECMs6gIAAAAAAABAjJS78gs2/5GtcePGlVFPUN5tu+22Oe3XtGlTE9u34vseeughp92jRw+nvXLlypyOn8mECRPSxogH/9H8iy++2GlfccUVkfvaj8B/+eWXpdovbBy7/EImiUTCaS9YsCAf3cnJDjvs4LT32GMPE1N+oTj17du3rLuAHNjXvZUrV8778ebOneu077nnnrSx5D66ei5QoHAAAA+KSURBVN555zk5+/HFo446ysl9/vnnG91PZFaIsWLzH6tu3769iXfeeefI/R555BGnPWPGjNLtGGLLHzeZzmGLFy82sf99DaXD/v946NChkdv5JVW6d+9u4pNOOsnJ1alTx8QdOnTY2C5ukF+mxv5z+KVfunXrZuJcyyoi2mabbWZi//vx/PnzTWyXh5Okf//73yb2S31sscUWJj7kkEMyHj8Igshc1apVM+5bXnGnLgAAAAAAAADECIu6AAAAAAAAABAjLOoCAAAAAAAAQIyUeU1du/6F9Ne6TEA2atSoYeJMdVJ8l112mYlr1arl5J5++mkTX3TRRRvRu+zYfwZJWrVqlYnzUbMX//PNN9847T333NPEdevWdXJffPFFVp+51VZbOW2/7nMYhpH7vv322yZeuHBhVsdDYdg1uTLNNWPHji1Ed7JWqdL/foe7du3aMuwJgGIwZMgQE48YMcLJ2fPfq6++6uTs66mRI0fmqXcVy+rVq532jz/+aGK/vv/hhx9u4okTJ+Z0PL/O4Wmnnea0b7nllqw+57HHHsvp+Ch+HTt2dNr+eoHNrqNbnt5fAHf+988Fdu1v/zuwza+d6n9/+v333yP3TSaTJj777LOdnH09b79bQpIGDBhg4muuucbJ8a6TjWfXrd1pp50it3v55Zedtv39ZcqUKU7OPu+9/vrrGY9/6KGHpu2LJN18880mnjdvnpN74oknMn5uWeJOXQAAAAAAAACIERZ1AQAAAAAAACBGWNQFAAAAAAAAgBgp85q6J510ktNu3LixiefOnVvo7uTs2GOPjcz5ta5Q+uz6OplqlfrsumD+fn7NsHyw66yec845Ts6vUYf8Offcc512zZo1TdyhQwcnZ9fbLQl/jjj99NNN3LlzZyc3ePDgnI6B/Nt3331NXJK5pqzZdaji1G8A5Z9/vW7Xzb3rrruc3IMPPmjiRo0aObl77rknD70rfv57F9q0aWNi/50Bt912m4nt+rqS9MILL5h4t912c3J2zcvWrVs7Ob/m5eLFi0285ZZbOrmZM2ea+KeffhKwXpMmTUx84403Rm63dOlSp/3www/nrU/YOPb7RZo2berkxo8fb+JM7w/ZmHeL9OjRw8TPPvuskxs0aJCJ/Zq6hx12mIn9GuFHHXVUzv1Byp9//mni7777zsnVr1/fxHZ9W0l6/PHHTZyplvKG2Oeh7bff3snZ7zS64IILnBw1dQEAAAAAAAAApYJFXQAAAAAAAACIkTIvvxBXLVu2dNrHHHNM5LbXXXddvruDHNm31f/f//2fk7Pb1157rZMbMmSI0543b15Ox7dLLCxbtszJ+Y8sIn+WL1/utDt27Gjitm3bOrlWrVpFfs7kyZNN/Prrrzu5gQMHOu0uXbqYeNq0aU5u+vTpmTsMbIQlS5Y47VznLwBI57333jOx/6jq2LFjTXznnXc6OcovlI5Zs2aZ+NRTT3VyvXv3NnH79u2dnN22H0GVpP/+978mHjNmjJMbNmyY037llVdM7Jf7efvtt008f/78tP1HxWA/mi+588EWW2wRud8NN9zgtKdOnVq6HUPO7O9Pkjun2yUHJalr164mfumll/LbMbnlHiTp4IMPNvGECROc3M4772ziAw880MkdeeSRJh49enRpdrHCWLFihYntsnaSVKXK/5YnS+scsd122znt2rVrm3jixIlO7owzzjCxvzZTnnGnLgAAAAAAAADECIu6AAAAAAAAABAjLOoCAAAAAAAAQIxQU7cE7Dq6V1xxhZOrVauWiT/44AMn98Ybb+S3YxWQX5enQYMGOX2OXUuyRYsWTm7UqFEm7t+/v5Oz6+lIbk3lP/74IzLXp08fJ9e8eXMT33jjjU7uo48+yth3FIZfO85vZ+vCCy902naduU8//dTJzZkzJ6djAOudfvrpkbm+ffs6bb+WGOLBnov82t8+++/c//sH8mnu3LlOe9y4cSbeddddC92dCse+lpXcev/++0FsK1eudNqZzhNNmzZ12ptuumnktsOHD4/MoWLp1auX0z722GMjt/3hhx9MfO+99+atT9g41atXd9r293V/XnjhhRdMbNe3lQrzHdj+vn7KKac4uQ8//NDENWrUcHLXXHONiampu/EWL16c92P46zZ2zW67BrwkTZo0Ke/9yQfu1AUAAAAAAACAGGFRFwAAAAAAAABipMzLL/z4449O2390vSxVrlzZaV911VUmPvnkk53czz//nHY7SVq9enUeelex/fLLL077u+++M3GjRo2cXPv27U384IMPOrlly5aZePbs2U5u3333NbFdQkGSpkyZ4rTt8ht33XWXkzvnnHPSHk9ySy74JR4QbzvuuGPG/JIlS0x8zz335Lk3KC3244L+Y1dbbbWViR955BEnd/bZZ+e3Yx67L5Jb0mPw4MEF7QuAissvsdCpUycTf/PNN4XuToW3atUqE5fWI87bbbdd1tt+/PHHpXJMxE/Xrl2d9uWXXx657dKlS522PW+sXbu2dDuGUjNs2DCnbc8Nt912m5MLgsDE/ppLoe29995O2+6bL66P51dktWvXjszlWlaxvOFOXQAAAAAAAACIERZ1AQAAAAAAACBGWNQFAAAAAAAAgBgp85q67777rtO2a9PWrFnTydk1AufOnVsqx99rr72c9sUXX2ziFi1aOLlWrVpFfs6pp55qYupFFZ5dt/bVV191ch06dDDxG2+84eQGDBhgYr+mrm3//fd32tdee21k3q/D8+2335q4d+/eTm7kyJGRx0S8XX/99RnzL7/8soknTJiQ7+6glHz55Zcm7tmzp5N77LHHTHziiSc6ufvvv9/E+fr7fuihh0y89dZbO7nnn3/exCtWrMjL8ZFfbdu2zdhGcfPrT9p1socOHVro7mRkv9vgpptucnKbb765if15EvHUpUuXsu4Cyqk2bdqY2H+vSaa6pWeeeabT/vrrr0u1XyiMIUOGmPjII490cu3atTPxE0884eTGjh1r4ltvvdXJTZs2Lae+9OjRw2mfe+65Jm7cuLGTyzQ2UVz+/PPPsu5CqeBOXQAAAAAAAACIERZ1AQAAAAAAACBGyrz8QibNmjVz2qNHjzZxpkflS+KAAw5w2nXr1o3c1i75MGrUKCf36aeflkp/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\n",
      "text/plain": [
       "<Figure size 1800x288 with 20 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# obtain one batch of test images\n",
    "dataiter = iter(test_loader)\n",
    "images, labels = dataiter.next()\n",
    "\n",
    "# get sample outputs\n",
    "output = model(images)\n",
    "# convert output probabilities to predicted class\n",
    "_, preds = torch.max(output, 1)\n",
    "# prep images for display\n",
    "images = images.numpy()\n",
    "\n",
    "# plot the images in the batch, along with predicted and true labels\n",
    "fig = plt.figure(figsize=(25, 4))\n",
    "for idx in np.arange(20):\n",
    "    ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])\n",
    "    ax.imshow(np.squeeze(images[idx]), cmap='gray')\n",
    "    ax.set_title(\"{} ({})\".format(str(preds[idx].item()), str(labels[idx].item())),\n",
    "                 color=(\"green\" if preds[idx]==labels[idx] else \"red\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The MNIST training example code is mainly taken from the [mnist_mlp_solution_with_validation.ipynb](https://github.com/udacity/deep-learning-v2-pytorch/blob/master/convolutional-neural-networks/mnist-mlp/mnist_mlp_solution_with_validation.ipynb) notebook from the [deep-learning-v2-pytorch repository](https://github.com/udacity/deep-learning-v2-pytorch) made by [Udacity](https://www.udacity.com/), and has been fitted with my early stopping code. "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
